package com.example.demo.thread.queue;

import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

public class TestQueue {
	@Test
	public void method1() throws InterruptedException {
		ArrayBlockingQueue<String> ab = new ArrayBlockingQueue<>(3);
		new Thread(() -> {
			for (int i = 0; i < 6; i++) {
				try {
					ab.offer(i + "", 2000, TimeUnit.SECONDS);
					System.out.println(ab + " " + Thread.currentThread().getName());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		Thread.sleep(2000);
		new Thread(() -> {
			for (int i = 0; i < 2; i++) {
				ab.poll();
				System.out.println(ab + " " + Thread.currentThread().getName());
			}
		}).start();
		Thread.currentThread();
		try {

			Thread.sleep(5000);

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(ab + " " + Thread.currentThread().getName());
	}

	@Test
	public void method2() {
		SynchronousQueue<String> sq = new SynchronousQueue<String>();
		// iterator() 永远返回空，因为里面没东西。
		// peek() 永远返回null
		/**
		 * isEmpty()永远是true。 remainingCapacity() 永远是0。 remove()和removeAll() 永远是false。
		 */
		new Thread(() -> {
			try {
				// 取出并且remove掉queue里的element（认为是在queue里的。。。），取不到东西他会一直等。
				System.out.println(sq.take());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}).start();
		try {
			Thread.currentThread().sleep(1000);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		new Thread(() -> {
			try {
				// offer() 往queue里放一个element后立即返回，
				// 如果碰巧这个element被另一个thread取走了，offer方法返回true，认为offer成功；否则返回false
				// true ,上面take线程一直在等,
				//// 下面刚offer进去就被拿走了,返回true,如果offer线程先执行,则返回false
				System.out.println(sq.offer("b"));

			} catch (Exception e) {
				e.printStackTrace();
			}

		}).start();
		new Thread(() -> {
			try {
				// 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走
				sq.put("a");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}).start();
	}

	@Test
	public void method3() throws InterruptedException {
		ArrayBlockingQueue<String> ab = new ArrayBlockingQueue<>(10);
		new Thread(() -> {
			for (int i = 0; i < 6; i++) {
				try {
					ab.offer(i + "", 100, TimeUnit.SECONDS);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(ab + " " + Thread.currentThread().getName());
			}
		}).start();
		new Thread(() -> {
			for (int i = 0; i < 6; i++) {
				try {
					ab.offer(i + "i", 100, TimeUnit.SECONDS);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(ab + " " + Thread.currentThread().getName());
			}
		}).start();
	}

	@Test
	public void method4() {
		// 队列里元素必须实现Comparable接口,用来决定优先级
		PriorityBlockingQueue<String> pbq = new PriorityBlockingQueue<String>();
		pbq.add("q");
		pbq.add("a");
		// 获取的时候会根据优先级取元素,插入的时候不会排序,节省性能
		// System.out.println(pbq.take());//a,获取时会排序,按优先级获取
		System.out.println(pbq.toString());// 如果前面没有取值,直接syso也不会排序
		Iterator<String> iterator = pbq.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
	
	@Test
	public void method5() {
		class Person implements  Delayed{
			private String field1;
			private long tigger;
			private long delayMilliSecound ;
			public Person(String field1, long delayMilliSecound) {
				this.field1=field1;
				this.delayMilliSecound=delayMilliSecound;
				this.tigger=delayMilliSecound+System.currentTimeMillis();
			}
			@Override
			public String toString() {
				return "Person [field1=" + field1 + ", delayMilliSecound=" + delayMilliSecound + "]";
			}
			public String getField1() {
				return field1;
			}
			public void setField1(String field1) {
				this.field1 = field1;
			}
			public long getField2() {
				return delayMilliSecound;	
			}
			public void setField2(long delayMilliSecound) {
				this.delayMilliSecound = delayMilliSecound;
			}
			@Override
			public int compareTo(Delayed o) {
				Person person = (Person) o;
				if(this.delayMilliSecound==person.getField2()) return 0;
				return this.delayMilliSecound-person.getField2()>0?1:-1;
			}
			@Override
			public long getDelay(TimeUnit unit) {
				return unit.convert(this.getField2()-System.currentTimeMillis(),TimeUnit.MILLISECONDS);
			}
		};
		DelayQueue<Person> dq = new DelayQueue<>();
		for (int i = 0; i < 5; i++) {
			Person per = new Person("name"+i,System.currentTimeMillis()+ new Random().nextInt(5000));
			dq.add(per);

		}
		
		for(;;) {
			try {
				System.out.println(dq.take());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
		
	}
	
	
}
